﻿using System;
using CoreRay;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CoreRay.Testing
{
    /// <summary>
    /// This is a test class for VertexBufferTest and is intended
    /// to contain all VertexBufferTest Unit Tests
    /// </summary>
    [TestClass]
    public class VertexBufferTest
    {
        /// <summary>
        /// Constructor test.
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Position", typeof(Vector3));
            vertexFormat.AddElement("Normale", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            VertexFormat expected = vertexFormat;
            VertexFormat actual = vertexBuffer.VertexFormat;

            // Verify
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        /// Write float test.
        /// </summary>
        [TestMethod]
        public void WriteFloatTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(float));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            vertexBuffer.Write(5.0f);

            float expected = 5.0f;
            float actual = vertexBuffer.GetVertexElement<float>(0, "Test"); ;

            // Verify
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        /// Write float bad test.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void WriteFloatBadTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(float));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            vertexBuffer.Write(new Vector3(1, 4, 5));
        }

        /// <summary>
        /// Write Vector3 test.
        /// </summary>
        [TestMethod]
        public void WriteVector3Test()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            Vector3 testValue = new Vector3(4.5f, -2.34f, 9.56f);

            vertexBuffer.Write(testValue);

            Vector3 expected = testValue;
            Vector3 actual = vertexBuffer.GetVertexElement<Vector3>(0, "Test"); ;

            // Verify
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        /// Write Vector3 bad test.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void WriteVector3BadTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            vertexBuffer.Write(5.0f);
        }

        /// <summary>
        /// Multiple write test.
        /// </summary>
        [TestMethod]
        public void MultipleWriteTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("TestElement1", typeof(Vector3));
            vertexFormat.AddElement("TestElement2", typeof(float));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            vertexBuffer.Write(new Vector3(3.5f, 2.8f, -9.4f));
            vertexBuffer.Write(7.8f);

            vertexBuffer.Write(new Vector3(7.1f, 4.6f, 42.5f));
            vertexBuffer.Write(5.6f);

            vertexBuffer.Write(new Vector3(475.11f, 5.7f, 678.4f));
            vertexBuffer.Write(-98.1f);

            // Verify
            Assert.AreEqual(new Vector3(7.1f, 4.6f, 42.5f), vertexBuffer.GetVertexElement<Vector3>(1, "TestElement1"));
            Assert.AreEqual(5.6f, vertexBuffer.GetVertexElement<float>(1, "TestElement2"));
        }

        /// <summary>
        /// GetVertexElement wrong type test.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidCastException))]
        public void GetVertexElementWrongTypeTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            Vector3 testValue = new Vector3(4.5f, -2.34f, 9.56f);

            vertexBuffer.Write(testValue);
            vertexBuffer.GetVertexElement<float>(0, "Test"); ;
        }

        /// <summary>
        /// GetVertexElement wrong index test.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void GetVertexElementWrongIndexTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            Vector3 testValue = new Vector3(4.5f, -2.34f, 9.56f);

            vertexBuffer.Write(testValue);
            vertexBuffer.GetVertexElement<float>(2, "Test"); ;
        }

        /// <summary>
        /// GetVertexElement wrong elementName test.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetVertexElementWrongElementNameTest()
        {
            // Setup
            VertexFormat vertexFormat = new VertexFormat();
            vertexFormat.AddElement("Test", typeof(Vector3));

            VertexBuffer vertexBuffer = new VertexBuffer(vertexFormat);

            // Execute
            Vector3 testValue = new Vector3(4.5f, -2.34f, 9.56f);

            vertexBuffer.Write(testValue);
            vertexBuffer.GetVertexElement<float>(0, "Test3"); ;
        }
    }
}
